﻿using Microsoft.Win32;
using Prism.Commands;
using Prism.Events;
using Prism.Regions;
using Prism.Services.Dialogs;
using SmartPlant.Core;
using SmartPlant.Core.Mvvm;
using SmartPlant.Model;
using SmartPlant.Model.DbContext.Biz;
using SmartPlant.Services;
using SmartPlant.Services.Interfaces;
using SmartPlant.WinCore;
using SmartPlant.WinCore.Helper;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Windows.Controls;
using System.Windows.Input;
using Telerik.Windows.Documents.Spreadsheet.FormatProviders;
using Telerik.Windows.Documents.Spreadsheet.FormatProviders.OpenXml.Xlsx;
using Telerik.Windows.Documents.Spreadsheet.Model;
using Unity;

namespace SmartPlant.Modules.Base.ViewModels
{
    public class IndexTableOutputViewModel : RegionViewModelBase, INotifyPropertyChanged
    {
        private DelegateCommand<object> _outputCommand;
        private DelegateCommand<object> _saveFileCommand;
        private DelegateCommand<SelectionChangedEventArgs> _templateSelectChangedCommand;
        private DelegateCommand<EventArgs> _templateDropDownOpenedCommand;
        private DelegateCommand<object> _refreshTemplatesCommand;

        private string _busyContent = "数据导出中.....";
        private bool _isBusy;
        private readonly BackgroundWorker backgroundWorker;
        private readonly ITemplateSettingService _tempServ;
        private readonly IAchievementService _OutputService;
        private readonly IEventAggregator _eventAggregator;
        private readonly ITaskJobService _taskJobService;
        private ObservableCollection<ComboBoxItemModel<SimpleStringModel>> _templatePathList;
        public List<ComboBoxItemModel<SimpleStringModel>> ComboxList { get; set; } = new List<ComboBoxItemModel<SimpleStringModel>>();
        private List<Report> _reports;
        private List<ITreeNodeModel> _currentNodes = null;
        public ObservableCollection<ComboBoxItemModel<SimpleStringModel>> TemplatePathList
        {
            get { return _templatePathList; }
            set { SetProperty(ref _templatePathList, value); }
        }

        public IndexTableOutputViewModel(
            IEventAggregator eventAggregator,
            IRegionManager regionManager,
            ITemplateSettingService tempServ,
            IAchievementService OutputService,
            IDialogService dialog,
            IUnityContainer unityContainer)
           : base(regionManager, unityContainer, dialog)
        {
            _tempServ = tempServ;
            _taskJobService = unityContainer.Resolve<TaskJobService>();
            _OutputService = OutputService;
            _eventAggregator = eventAggregator;
            _eventAggregator.GetEvent<PlanSelectedEvent>().Subscribe(OnPlanSelectedEvent);
            ComboxList.Add(new ComboBoxItemModel<SimpleStringModel> { Description = "分单元出图", IsEnable = true, SelectedModel = new SimpleStringModel { v1 = "0" } });
            ComboxList.Add(new ComboBoxItemModel<SimpleStringModel> { Description = "合并出图", IsEnable = true, SelectedModel = new SimpleStringModel { v1 = "1" } });
            this.SelectedModel = ComboxList[0].SelectedModel;

            backgroundWorker = new BackgroundWorker();
            backgroundWorker.DoWork += this.OnBackgroundWorkerDoWork;
            backgroundWorker.RunWorkerCompleted += OnBackgroundWorkerRunWorkerCompleted;

            if (GlobalObject.CurrentNodes != null && GlobalObject.CurrentNodes.Count > 0)
            {
                OnPlanSelectedEvent(GlobalObject.CurrentNodes);
            }
        }

        private async void OnPlanSelectedEvent(List<ITreeNodeModel> treeNodes)
        {
            _currentNodes = treeNodes;
            string units = _currentNodes.ExpandToString(t => t.Id, ",");
        }

        protected override async void OnInitPage(object obj)
        {
            excelIsEnable = true;
            base.OnInitPage(obj);
            //var str = await _specOutputService.SpecOutputTemplatePath(GlobalObject.CurrentProject.ProjId.ToString());
            //_reports = await _tempServ.GetTemplateLisAsync(GlobalObject.CurrentProject.ProjId.ToString());
            //_reports = _reports.Where(x => x.InOrOut == 1 && x.Type == TemplateType.INDEX).ToList();
            //var list = new ObservableCollection<ComboBoxItemModel<SimpleStringModel>>();
            //_reports.ForEach(x =>
            //{
            //    list.Add(new ComboBoxItemModel<SimpleStringModel>()
            //    {
            //        Name = x.Name,
            //        Description = x.Description,
            //        IsEnable = true,
            //        SelectedModel = new SimpleStringModel { v1 = x.Name }
            //    });
            //});

            //TemplatePathList = list;
            //if (list.Count > 0)
            //{
            //    SelectedTempateModel = list[0].SelectedModel;
            //}
            await Task.Run(() => LoadReports(null));

        }



        /// <summary>
        /// 用于显示数据获取的进度文本。
        /// </summary>
        public string BusyContent
        {
            get { return _busyContent; }
            set { SetProperty(ref _busyContent, value); }
        }
        /// <summary>
        /// 当前是否处理忙碌状态。
        /// </summary>
        public virtual bool IsBusy
        {
            get { return _isBusy; }
            set
            {
                if (this._isBusy != value)
                {
                    this._isBusy = value;
                    this.OnPropertyChanged(nameof(IsBusy));
                    if (_isBusy)
                    {
                        backgroundWorker.RunWorkerAsync();
                    }
                }
            }
        }

        private SimpleStringModel _selectedTemplateModel;
        public SimpleStringModel SelectedTempateModel
        {
            get { return _selectedTemplateModel; }
            set
            {
                SetProperty(ref _selectedTemplateModel, value);
            }
        }

        private SimpleStringModel _selectedModel;
        public SimpleStringModel SelectedModel
        {
            get { return _selectedModel; }
            set { SetProperty(ref _selectedModel, value); }
        }
        private Workbook _workbook = null;
        public Workbook TemplateWorkbook
        {
            get { return _workbook; }
            set { SetProperty(ref _workbook, value); }
        }
        private bool _excelIsEnable;

        public bool excelIsEnable
        {
            get { return _excelIsEnable; }
            set { _excelIsEnable = value; }
        }

        private string _fielPath;//保存Excel模板路径
        public string FilePath
        {
            get { return _fielPath; }
            set { SetProperty(ref _fielPath, value); }
        }

        private string _outputFilePath;//保存输出文件路径
        public string OutputFilePath
        {
            get { return _outputFilePath; }
            set { SetProperty(ref _outputFilePath, value); }
        }

        public System.Windows.Input.ICommand OutputCommand
        {
            get
            {
                if (_outputCommand != null) return _outputCommand;
                _outputCommand = new DelegateCommand<object>(onOutputCommand);
                return _outputCommand;
            }
        }

        public System.Windows.Input.ICommand SaveFileCommand
        {
            get
            {
                if (_saveFileCommand != null) return _saveFileCommand;
                _saveFileCommand = new DelegateCommand<object>(onSaveFileCommandAsync);
                return _saveFileCommand;
            }
        }
        public ICommand TemplateSelectChangedCommand
        {
            get
            {
                if (_templateSelectChangedCommand != null) return _templateSelectChangedCommand;
                _templateSelectChangedCommand = new DelegateCommand<SelectionChangedEventArgs>(onTemplateSelectChangedCommand);
                return _templateSelectChangedCommand;
            }
        }
        public ICommand TemplateDropDownOpenedCommand
        {
            get
            {
                if (_templateDropDownOpenedCommand != null) return _templateDropDownOpenedCommand;
                _templateDropDownOpenedCommand = new DelegateCommand<EventArgs>(onTemplateDropDownOpenedCommand);
                return _templateDropDownOpenedCommand;
            }
        }

        public ICommand refreshTemplatesCommand
        {
            get
            {
                if (_refreshTemplatesCommand != null) return _refreshTemplatesCommand;
                _refreshTemplatesCommand = new DelegateCommand<object>(LoadReports);
                return _refreshTemplatesCommand;
            }
        }
        private async void LoadReports(object obj)
        {
            _reports = await _tempServ.GetTemplateLisAsync(GlobalObject.CurrentProject.ProjId.ToString());
            _reports = _reports.Where(x => x.InOrOut == 1 && x.Type == TemplateType.INDEX).ToList();
            var list = new ObservableCollection<ComboBoxItemModel<SimpleStringModel>>();
            _reports.ForEach(x =>
            {
                list.Add(new ComboBoxItemModel<SimpleStringModel>()
                {
                    Name = x.Name,
                    Description = x.Description,
                    IsEnable = true,
                    SelectedModel = new SimpleStringModel { v1 = x.Name }
                });
            });

            TemplatePathList = list;
            if (list.Count > 0)
            {
                SelectedTempateModel = list[0].SelectedModel;
            }
        }

        private void onSaveFileCommandAsync(object obj)
        {
            var saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "Zip压缩文件|*.zip";
            var r = saveFileDialog.ShowDialog();
            if (r.HasValue)
            {
                OutputFilePath = saveFileDialog.FileName;
            }
        }
        private void onOutputCommand(object obj)
        {
            if (_fielPath.IsNullOrEmpty())
            {
                var message = "本地输出路径不能为空！！！";
                Dialog.ShowAltert(message);
                return;
            }
            if (SelectedTempateModel == null)
            {
                var message = "请选择一个 输出配置！！！";
                Dialog.ShowAltert(message);
                return;
            }

            if (_currentNodes == null)
            {
                Dialog.ShowAltert("导出前请至少选择一个单元！！！");
                return;
            }
            string units = _currentNodes.ExpandToString(t => t.Id, ",");
            if (units.IsNullOrEmpty())
            {
                Dialog.ShowAltert("导出前请至少选择一个单元！！！");
                return;
            }
            this.IsBusy = true;





            this.IsBusy = false;
        }

        /// <summary>
        /// 后台任务数据加载完成执行的方法。
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnBackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            InvokeOnUIThread(() =>
            {
                var result = e.Result as RESTfulResult;
                this.IsBusy = false;
                if (result.succeeded)
                {
                    Dialog.ShowMessage(result.msg);
                }
                else
                {
                    Dialog.ShowAltert(result.msg);
                }

            });
        }

        private void OnBackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
        {
            var task = ExportFileAsync(null);
            while (!task.IsCompleted)
            {
                Thread.Sleep(1000);
            }
            e.Result = task.Result;
        }

        /// <summary>
        /// 执行后台视图数据加载服务。
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        protected async virtual Task<object> ExportFileAsync(object model)
        {
            string units = _currentNodes.ExpandToString(t => t.Id, ",");
            bool exportflag = SelectedModel.v1 == "0";
            var proid = GlobalObject.CurrentProject.ProjId.ToString();
            var result = new RESTfulResult { succeeded = false };
            try
            {
                var templatePath = _reports.FirstOrDefault(x => x.Name == _selectedTemplateModel.v1)?.TemplatePath;
                var rr = await _OutputService.IndexTableOutputAsync(proid, units, templatePath, SelectedTempateModel.v1, exportflag);
                if (!rr.succeeded)
                {
                    LoggerHelper.Current.Error(rr.errors.ToString());
                    result.msg = rr.errors.ToString();
                    return result;
                }
                var taskId = rr.data;

                while (true)
                {
                    try
                    {
                        TaskJob task = await _taskJobService.GetJobAsync(GlobalObject.CurrentProject.ProjId.ToString(), taskId);
                        if (task != null)
                        {
                            if (task.FINISHED == 1)
                            {
                                break;//结束了，且成功
                            }
                            else if (task.FINISHED == -1)
                            {
                                string msg = $"导出索引表成品失败：{task.NOTE}";
                                result.msg = msg;
                                return result;
                                //结束了，但是中途错误
                            }
                            BusyContent = $"导出中...正在处理{task.NOTE}";
                            Thread.Sleep(2000);
                        }
                        else
                        {
                            string msg = $"无法查询到任务{taskId}";
                            result.msg = msg;
                            return result;

                        }

                    }
                    catch (Exception x)
                    {
                        string msg = $"导出索引表成品失败：{x.Message}";
                        LoggerHelper.Current.Error(msg, x);
                        result.msg = msg;
                        return result;
                    }
                }

                var rFile = await _taskJobService.DownloadFileAsync(GlobalObject.CurrentProject.ProjId.ToString(), taskId);

                if (!rFile.succeeded)
                {
                    rr.msg = rFile.msg;
                    return rr;
                }
                var content = Convert.FromBase64String(rFile.data.Data);

                FileHelper.WriteFileBinary(OutputFilePath, content);
                //using var stream =  rr.data;
                //var r = await FileHelper.WriteFileStreamAsync(stream, OutputFilePath);
                result.msg = "导出文件到本地成功！！！";
                result.succeeded = true;
                return result;
            }
            catch (Exception x)
            {
                var xMessage = $"导出文件到本地失败：{x.Message}！！！";
                LoggerHelper.Current.Error(xMessage, x);
                result.msg = xMessage;
                return result;
            }
        }
        private async void onTemplateSelectChangedCommand(SelectionChangedEventArgs obj)
        {
            var eventArgs = obj as SelectionChangedEventArgs;
            if (eventArgs == null) return;
            if (eventArgs.AddedItems.Count < 1) return;


            var report = _reports.FirstOrDefault(x => x.Name == _selectedTemplateModel.v1);
            if (report != null && report.Name.IsNotEmptyOrNull())
            {
                try
                {

                    var report2 = report.CloneObject();
                    if (!report2.Name.EndsWith(".xlsx"))
                    {
                        report2.Name += ".xlsx";
                    }
                    var result = await _tempServ.DownloadTemplateFileAsync(GlobalObject.CurrentProject.ProjId.ToString(), report2);
                    if (!result.succeeded)
                    {
                        LoggerHelper.Current.Error(result.errors.ToString());

                        Dialog.ShowAltert("模板配置文件不存在，请选中其他模板！！！");
                        FilePath = "";
                        this.TemplateWorkbook = new Workbook();
                        excelIsEnable = false;
                        return;
                    }
                    FilePath = AppDomain.CurrentDomain.BaseDirectory.CombinePath("\\Templates\\" + report.Name);
                    using var stream = result.data;
                    var content = await FileHelper.ReadFileContentAsync(stream);
                    FileHelper.WriteFileBinary(FilePath, content);
                    try
                    {
                        var workBook = OpenXlsxFile(FilePath);
                        this.TemplateWorkbook = workBook;
                        excelIsEnable = true;
                        return;
                    }
                    catch (Exception x)
                    {
                        Dialog.ShowAltert("打开Excel文件失败，文件可能已加密(损坏)或已被其它进程打开。");
                        FilePath = "";
                        this.TemplateWorkbook = new Workbook();
                    }
                }
                catch (Exception x)
                {
                    string msg = $"下载模板文件失败：{x.Message}";
                    LoggerHelper.Current.Error(msg, x);
                    Dialog.ShowAltert(msg);
                }
            }
        }
        private async void onTemplateDropDownOpenedCommand(EventArgs obj)
        {
            //估计是为了解决 刷新同步 而做的，但是我感觉能不能从判断当前页面是否重新被active来判断，而不是下拉展开来判断，或者干脆做一个刷新按钮
            //var name = SelectedTempateModel?.v1;

            //_reports = await _tempServ.GetTemplateLisAsync(GlobalObject.CurrentProject.ProjId.ToString());
            //_reports = _reports.Where(x => x.InOrOut == 1 && x.Type == TemplateType.INDEX).ToList();
            //var list = new ObservableCollection<ComboBoxItemModel<SimpleStringModel>>();
            //_reports.ForEach(x =>
            //{
            //    list.Add(new ComboBoxItemModel<SimpleStringModel>()
            //    {
            //        Name = x.Name,
            //        Description = x.Description,
            //        IsEnable = true,
            //        SelectedModel = new SimpleStringModel { v1 = x.Name }
            //    });
            //});

            //TemplatePathList = list;
            //if (list.Count > 0)
            //{
            //    SelectedTempateModel = list.FirstOrDefault(x => x.SelectedModel.v1 == name)?.SelectedModel;
            //}
            //;
        }
        private Workbook OpenXlsxFile(string file)
        {
            byte[] fileAsByteArray = File.ReadAllBytes(file);
            return OpenXlsxFile(fileAsByteArray);
        }
        private Workbook OpenXlsxFile(byte[] content)
        {
            IBinaryWorkbookFormatProvider formatProvider = new XlsxFormatProvider();
            Workbook workbook = formatProvider.Import(content);
            return workbook;
        }
    }
}
